//关于棍料开料逻辑

import type { divide_demand_sum, stick_propose, stick_propose_detail } from '@/types/billdata'
import type { t_remainder_stick } from '@/types/producedata'
import { make_billcode, sum } from './common'
import { groupDividePropose } from './groupUtils'

export const stick_usage_cal = (demand: divide_demand_sum) => {
  if (demand.supply_length[0].seq === 1) {
    return stick_usage_cal_unlimit(demand)
  }
}

const stick_make_remainder = (
  stick_propose_detail: stick_propose_detail,
  tmp_remainder_stick: t_remainder_stick[]
) => {
  if (stick_propose_detail === null) return
  const unit_remainder = stick_propose_detail.unit_remainder!
  const last_remainder = stick_propose_detail.last_remainder!
  const from_info = `${stick_propose_detail.stick_length}->${stick_propose_detail.divide_length}*${stick_propose_detail.last_output}`
  const remainder_stick: t_remainder_stick = {
    from_propose_detail: stick_propose_detail.id,
    src_remainder: stick_propose_detail.use_remainder_id,
    first_propose_detail:
      stick_propose_detail.first_propose_detail === undefined
        ? stick_propose_detail.id
        : stick_propose_detail.first_propose_detail,
    first_remainder:
      stick_propose_detail.first_remainder_id === undefined
        ? stick_propose_detail.use_remainder_id
        : stick_propose_detail.first_remainder_id,
    id: make_billcode('R'),
    re_input: 0,
    from: from_info,
    qty: 0,
    length: 0,
    balance: 0
  }
  if (unit_remainder === last_remainder) {
    if (unit_remainder > 0) {
      remainder_stick.length = unit_remainder
      remainder_stick.qty = stick_propose_detail.stick_qty
    }
  } else if (stick_propose_detail.stick_qty === 1) {
    if (last_remainder > 0) {
      remainder_stick.length = last_remainder
      remainder_stick.qty = 1
    }
  } else {
    if (unit_remainder > 0) {
      remainder_stick.length = last_remainder
      remainder_stick.qty = stick_propose_detail.stick_qty - 1
    }
    if (last_remainder > 0) {
      remainder_stick.length = last_remainder
      remainder_stick.qty = 1
    }
  }
  remainder_stick.balance = remainder_stick.qty
  tmp_remainder_stick.push(remainder_stick)
}
const stick_match_remainder = (
  remander: t_remainder_stick[],
  divide_length: number,
  demand_qty: number
) => {
  const result: stick_propose_detail[] = []
  let shortfall = demand_qty
  const matched_record = remander
    .filter((r) => r.length >= divide_length && r.balance > 0)
    .sort((a, b) => b.qty - a.qty)
  matched_record.forEach((r) => {
    if (shortfall === 0) return
    const propose = make_stick_propose_detail(r.length, divide_length, r.balance, shortfall, false)
    const matchqty = demand_qty - propose.shortfall
    if (matchqty > 0) {
      const detail = propose.propose_detail!
      detail.use_remainder_id = r.id
      detail.first_remainder_id = r.first_remainder === undefined ? r.id : r.first_remainder
      detail.src_divide = r.from
      detail.divide_length = divide_length
      detail.first_propose_detail = r.first_propose_detail
      r.re_input += detail.stick_qty
      r.balance -= detail.stick_qty
      stick_make_remainder(detail, remander)
      result.push(detail)
    }
    shortfall = propose.shortfall
    if (propose.shortfall === 0) return
  })
  return { shortfall: shortfall, result: result } //返回短缺数
}

const make_stick_propose_detail = (
  stick_length: number,
  divide_length: number,
  supply_stick_qty: number, //可供应的长棍，如果为-1则视为无限供应
  demand_qty: number,
  exclude_last_qty: boolean //如果最后一棒需求数小于可开料数，则可以排除并留在最后处理
) => {
  if (stick_length < divide_length) return { propose_detail: null, shortfall: demand_qty }
  const _unit_output = Math.floor(stick_length / divide_length) //每长棍开多少条短棍
  const _demand_stick_qty_exclude_last = Math.floor(demand_qty / _unit_output) //需求长棍(只取到整除部分)
  const last_divide_qty = exclude_last_qty ? 0 : demand_qty % _unit_output //最后一段开料数
  const _unit_remainder = stick_length - _unit_output * divide_length //单位余料
  const last_stick = last_divide_qty > 0 ? 1 : 0
  const _all_demand_stick = _demand_stick_qty_exclude_last + last_stick
  let _supply_stick_qty =
    supply_stick_qty === -1 ? _all_demand_stick : Math.min(_all_demand_stick, supply_stick_qty) //实际供应长棍
  if (_supply_stick_qty === 0) return { propose_detail: null, shortfall: demand_qty }
  let _last_remainder = last_stick * (stick_length - divide_length * last_divide_qty) //正常情况下最后余料等于棍长-开料长*尾料数,如果尾料不开，则尾余为单位余料
  if (_last_remainder === 0 && _demand_stick_qty_exclude_last > 0) _last_remainder = _unit_remainder
  const item: stick_propose_detail = {
    id: make_billcode('SPD'),
    last_output: _supply_stick_qty === 0 ? 0 : last_divide_qty > 0 ? last_divide_qty : _unit_output,
    stick_length: stick_length,
    divide_length: divide_length,
    unit_output: _unit_output, //一支长棍开多少支短棍
    stick_qty: _supply_stick_qty, //共消耗多少长棍
    all_output: (_supply_stick_qty - last_stick) * _unit_output + last_divide_qty, //共开出多少支短棍
    unit_remainder: _unit_remainder, //单位余料
    last_remainder: _last_remainder, //尾数余料
    all_remainder: (_supply_stick_qty - last_stick) * _unit_remainder + _last_remainder * last_stick //合共余料,(n-1)*unit_remainder+last_remainder
  }
  const result = {
    propose_detail: item,
    shortfall: demand_qty - item.all_output
  }
  return result
}
const make_stick_propose_detail_adv = (
  length_supply: number,
  divide_length: number,
  demand_qty: number,
  tmp_unhandle_demand: t_unhandle_demand[],
  tmp_remainder_stick: t_remainder_stick[],
  exclude_last_qty: boolean,
  supply_stick_qty: number
) => {
  if (demand_qty === 0) return null
  const item = make_stick_propose_detail(
    length_supply,
    divide_length,
    supply_stick_qty,
    demand_qty,
    exclude_last_qty
  )
  if (item.shortfall > 0) {
    tmp_unhandle_demand.push({ divide_length: divide_length, unhandle_demand: item.shortfall })
  }
  stick_make_remainder(item.propose_detail!, tmp_remainder_stick)
  return item.propose_detail
}
type t_unhandle_demand = { divide_length: number; unhandle_demand: number } //未处理尾料，有时候尾料会在最后使用余料进行开料
const stick_usage_cal_unlimit = (demand: divide_demand_sum) => {
  //这个策略是先正常开料，尾料不开，留到最后使用余料开，余料开不足部分再用正常料开
  const config = demand.supply_length[0]
  const result_item: stick_propose[] = []
  demand.divide_detail.sort((a, b) => b.length - a.length)
  const tmp_remainder_stick: t_remainder_stick[] = [] //临时余料库，运算过程中产生的余料暂时写到这里
  const tmp_unhandle_demand: t_unhandle_demand[] = []

  demand.divide_detail.forEach((r) => {
    const propose: stick_propose = {
      id: make_billcode('SP'),
      groupcode: demand.billcode,
      metal: demand.metal,
      section: demand.section,
      divide_length: r.length,
      details: [],
      all_demand_qty: r.demand_qty!,
      process: r.divide_demand_details.map((s) => {
        return {
          part_code: s.partcode,
          part_name: s.partname,
          mocode: s.mocode,
          demandcode: s.billcode,
          demand_qty: s.qty,
          length: s.length
        }
      })
    }
    const detail = make_stick_propose_detail_adv(
      config.length,
      r.length,
      r.demand_qty!,
      tmp_unhandle_demand,
      tmp_remainder_stick,
      true,
      -1
    )
    if (detail !== null) {
      propose.details?.push(detail)
    }
    result_item.push(propose)
  })

  //const use_normal_stick_again: { unhandle_demand: number; divide_length: number }[] = []
  tmp_unhandle_demand.forEach((r) => {
    const use_remainder = stick_match_remainder(
      tmp_remainder_stick,
      r.divide_length,
      r.unhandle_demand
    )
    if (use_remainder.result.length > 0) {
      const propose = result_item.find((t) => t.divide_length == r.divide_length)
      use_remainder.result.forEach((s) => {
        propose?.details?.push(s)
      })
    }
    const _item = make_stick_propose_detail_adv(
      config.length,
      r.divide_length,
      use_remainder.shortfall,
      tmp_unhandle_demand,
      tmp_remainder_stick,
      false,
      -1
    )
    if (_item !== null) {
      const propose = result_item.find((t) => t.divide_length == r.divide_length)
      propose?.details.push(_item)
    }
  })

  result_item.forEach((r) => {
    r.all_supply_qty = sum(r.details.map((s) => s.all_output))
  })
  const result = groupDividePropose(result_item)
  result[0].remainder = tmp_remainder_stick
  result[0].all_stick_length = sum(result[0].all_stick.map((r) => r.length * r.qty))
  result[0].all_remainder_length = sum(result[0].remainder.map((r) => r.length * r.balance))
  result[0].usage =
    (result[0].all_stick_length - result[0].all_remainder_length) / result[0].all_stick_length
  return result[0]
}
